// 1、变量初始化
// 其中symbol为变量在汇编语言中对应的标识符，offset是符号开始地址的偏移量，width是要初始化内存的宽度大小，value是要初始化的值。
// 其中当前包中Go语言定义的符号symbol，在汇编代码中对应·symbol，其中“·”中点符号为一个特殊的unicode符号。
// 格式
//DATA symbol+offset(SB)/with, value

// 示例
// 我们采用以下命令可以给Id变量初始化为十六进制的0x2537，对应十进制的9527（常量需要以美元符号$开头表示）：
//DATA .Id+0(SB)/1,$0x37
//DATA .Id+1(SB)/1,$0x25

// 2、符号提供其他代码使用
// Go汇编语言提供了GLOBL命令用于将符号导出
// 格式
//GLOBL symbol(SB),with

// 示例
// 其中symbol对应汇编中符号的名字，width为符号对应内存的大小。用以下命令将汇编中的·Id变量导出：
//GLOBL .Id,$8

// 现在已经初步完成了用汇编定义一个整数变量的工作。
// 为了便于其它包使用该Id变量，我们还需要在Go代码中声明该变量，同时也给变量指定一个合适的类型。修改pkg.go的内容如下：
//package pkg

//var Id int
// 现状Go语言的代码不再是定义一个变量，语义变成了声明一个变量（声明一个变量时不能再进行初始化操作）。
// 而Id变量的定义工作已经在汇编语言中完成了

// 声明Id变量，并赋值
// 错误： runtime.gcdata: missing Go type information for global symbol goland-study/go_code/go_advanced_programming/compilation/started_quickly.Id: size 8
// 错误提示汇编中定义的Id符号没有类型信息。
// 其实Go汇编语言中定义的数据并没有所谓的类型，每个符号只不过是对应一块内存而已，因此Id符号也是没有类型的。
// 但是Go语言是再带垃圾回收器的语言，而Go汇编语言是工作在自动垃圾回收体系框架内的。
// 当Go语言的垃圾回收器在扫描到Id变量的时候，无法知晓该变量内部是否包含指针，因此就出现了这种错误。
// 错误的根本原因并不是Id没有类型，而是Id变量没有标注是否会含有指针信息。
// 需要引入textflag.h。
#include "textflag.h"
//
//GLOBL ·Id(SB),NOPTR,$8
//
//DATA ·Id+0(SB)/1,$0x37
//DATA ·Id+1(SB)/1,$0x25
//DATA ·Id+2(SB)/1,$0x00
//DATA ·Id+3(SB)/1,$0x00
//DATA ·Id+4(SB)/1,$0x00
//DATA ·Id+5(SB)/1,$0x00
//DATA ·Id+6(SB)/1,$0x00
//DATA ·Id+7(SB)/1,$0x00

// 初始化字符串常量
//
// 因为在Go汇编语言中，go.string."gopher"不是一个合法的符号，
// 因此我们无法通过手工创建（这是给编译器保留的部分特权，因为手工创建类似符号可能打破编译器输出代码的某些规则）。
// 因此我们新创建了一个·NameData符号表示底层的字符串数据。
// 然后定义·Name符号内存大小为16字节，其中前8个字节用·NameData符号对应的地址初始化，后8个字节为常量6表示字符串长度。

//GLOBL ·NameData(SB),NOPTR,$8
//DATA ·NameData(SB)/8,$"gopher"
//
//GLOBL ·Name(SB),NOPTR,$16
//DATA ·Name+0(SB)/8,$·NameData(SB)
//DATA ·Name+8(SB)/8,$6

// 另外一种赋值方式
// 将底层的字符串数据和字符串头结构体定义在一起，这样可以避免引入NameData符号
// $·Name+16(SB) 获取Name变量，16偏移量的指针地址（Name值（"gopher"）的地址）（8位）
GLOBL ·Name(SB),NOPTR,$24

DATA ·Name+0(SB)/8,$·Name+16(SB)
DATA ·Name+8(SB)/8,$6
DATA ·Name+16(SB)/8,$"gopher"
